home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / package_16-january-2001.zip / Effects / cheapo stereo xfade.cpp < prev    next >
C/C++ Source or Header  |  2000-08-10  |  9KB  |  431 lines

  1. // Copyright (C) Mikko Apo (apo@iki.fi)
  2. // The following code may be used to write free software
  3. // if credit is given to the original author.
  4. // Using it for anything else is not allowed without permission
  5. // from the author.
  6.  
  7.  
  8. #include <stdlib.h>
  9. #include <time.h>
  10. #include <math.h>
  11. #include <string.h>
  12. #include "../mdk.h"
  13.  
  14. #define miCOMMAND_STRING "About..."
  15. #define miMACHINE_NAME "cheapo stereo xfade"
  16. #define miSHORT_NAME "ch.st.xfade"
  17. #define miMACHINE_AUTHOR "Mikko Apo (apo@iki.fi)"
  18. #define miMAX_TRACKS        0
  19. #define miMIN_TRACKS        0
  20. #define miNUMGLOBALPARAMETERS    5
  21. #define miNUMTRACKPARAMETERS    0
  22. #define miNUMATTRIBUTES    1
  23. #define miVERSION "1.0"
  24.  
  25. //    Parameters
  26.  
  27. CMachineParameter const paraMode = 
  28. { pt_byte, "Mode","Mode: 0 Separate, 1 Link, 2 Mirror, 3 Left Master, 4 Right Master",0,4,0xff,MPF_STATE,0 };
  29.  
  30. CMachineParameter const paraLXFade = 
  31. { pt_byte, "Left X-Fade","Left X-Fade",0,0xfe,0xff,MPF_STATE,0};
  32.  
  33. CMachineParameter const paraRXFade = 
  34. { pt_byte, "Right X-Fade","Right X-Fade",0,0xfe,0xff,MPF_STATE,0xfe };
  35.  
  36. CMachineParameter const paraInertia = 
  37. { pt_word, "Inertia","Inertia length",0,0xfffe,0xffff,MPF_STATE,1 };
  38.  
  39. CMachineParameter const paraInertiaUnit = 
  40. { pt_byte, "Inertia Unit","Inertia Unit: 0=tick (default), 1 ticks/256, 2 samples, 3=ms, 4=seconds",0,4,0xff,MPF_STATE,0 };
  41.  
  42. // List of all parameters, track parameters last
  43.  
  44. CMachineParameter const *pParameters[] = 
  45. { ¶Mode,¶LXFade,¶RXFade,¶Inertia,¶InertiaUnit };
  46.  
  47. // Attributes
  48.  
  49. CMachineAttribute const attrModeChange = { "Mode change: Normal inertia" ,0,1,0 };
  50.  
  51. // List of all attributes
  52.  
  53. CMachineAttribute const *pAttributes[] =
  54. { &attrModeChange };
  55.  
  56. #pragma pack(1)
  57.  
  58. class gvals
  59. {
  60. public:
  61.     byte mode;
  62.     byte lxfade;
  63.     byte rxfade;
  64.     word inertia;
  65.     byte inertiaunit;
  66. };
  67.  
  68. class avals
  69. {
  70. public:
  71.     int maxdelay;
  72. };
  73.  
  74. #pragma pack()
  75.  
  76. // Machine's info
  77.  
  78. CMachineInfo const MacInfo = 
  79. {
  80.     MT_EFFECT,MI_VERSION,MIF_DOES_INPUT_MIXING,miMIN_TRACKS,miMAX_TRACKS,
  81.     miNUMGLOBALPARAMETERS,miNUMTRACKPARAMETERS,pParameters,miNUMATTRIBUTES,pAttributes,
  82. #ifdef _DEBUG
  83.     miMACHINE_NAME" [DEBUG]"
  84. #else
  85.     miMACHINE_NAME
  86. #endif
  87.     ,miSHORT_NAME,miMACHINE_AUTHOR,miCOMMAND_STRING
  88. };
  89.  
  90.  
  91. class miex : public CMDKMachineInterfaceEx
  92. {
  93.  
  94. };
  95.  
  96. class mi : public CMDKMachineInterface
  97. {
  98. public:
  99.     mi();
  100.  
  101.     virtual void Command(int const i);
  102.     virtual void Tick();
  103.     virtual char const *DescribeValue(int const param, int const value);
  104.  
  105.     virtual void MDKInit(CMachineDataInput * const pi);
  106.     virtual bool MDKWork(float *psamples, int numsamples, int const mode) {return false;}
  107.     virtual bool MDKWorkStereo(float *psamples, int numsamples, int const mode);
  108.     virtual void MDKSave(CMachineDataOutput * const po) { }
  109.  
  110.     public:
  111.     virtual CMDKMachineInterfaceEx *GetEx() { return &ex; }
  112.     virtual void OutputModeChanged(bool stereo) {}
  113.  
  114.     public:
  115.     miex ex;
  116.     gvals gval;
  117.     avals aval;
  118.  
  119. private:
  120.  
  121.     unsigned long calculate_length(byte type, word len);
  122.  
  123.     float l_l_amp,l_r_amp,r_l_amp,r_r_amp;
  124.     int valInertia,valInertiaUnit;
  125.     bool l_inertia,r_inertia,first;    // inertia
  126.     float l_amp_inc,l_amp_target; //
  127.     float r_amp_inc,r_amp_target;  //
  128.     unsigned int l_counter,r_counter; //
  129.     int valMode;
  130.     float valLFade,valRFade;
  131. };
  132.  
  133.  
  134. DLL_EXPORTS
  135.  
  136. mi::mi()
  137. {
  138.     GlobalVals = &gval;
  139.     AttrVals = (int *)&aval;
  140. }
  141.  
  142. void mi::Command(int const i)
  143. {
  144.     switch(i)
  145.     {
  146.     case 0:
  147.         pCB->MessageBox(miMACHINE_NAME"\n\nBuild date: "__DATE__"\nVersion: "miVERSION"\nCoded by: "miMACHINE_AUTHOR"\nThanks to Zephod for showing how it's done.\n\nCheck out http://www.iki.fi/apo/buzz/\nfor more buzz stuff.\n\nExcellent skin made by Hymax.");
  148.         break;
  149.     }
  150. }
  151.  
  152. char const *mi::DescribeValue(int const param, int const value)
  153. {
  154.     static char txt[100];
  155.  
  156.     switch(param)
  157.     {
  158.     case 0:
  159.         switch(value)
  160.         {
  161.         case 0: return("Separate");
  162.         case 1: return("Link");
  163.         case 2: return("Mirror");
  164.         case 3: return("Left Master");
  165.         case 4: return("Right Master");
  166.         }
  167.         break;
  168.     case 1:
  169.     case 2:
  170.         sprintf(txt,"%2.1f%%:%2.1f%%",100.0*(1-((float)value)/0xfe),(float)((100.0*value)/0xfe));
  171.         break;
  172.     case 3:
  173.         sprintf(txt,"%d %s",value,DescribeValue(4,valInertiaUnit));
  174.         break;
  175.     case 4:
  176.         switch(value)
  177.         {
  178.         case 0: return("ticks");
  179.         case 1: return("ticks/256");
  180.         case 2:    return("samples");
  181.         case 3:    return("ms");
  182.         case 4: return("secs");
  183.         }
  184.         break;
  185.     }
  186.  
  187.     return txt;
  188. }
  189.  
  190. void mi::MDKInit(CMachineDataInput * const pi)
  191. {
  192.     valMode=paraMode.DefValue;
  193.     l_r_amp=valLFade=((float)paraLXFade.DefValue)/0xfe;
  194.     l_l_amp=(float)(1.0 - l_r_amp);
  195.     r_r_amp=valRFade=((float)paraLXFade.DefValue)/0xfe;
  196.     r_l_amp=(float)(1.0 - r_r_amp);
  197.     l_inertia=r_inertia=false;
  198.     valInertia=paraInertia.DefValue;
  199.     valInertiaUnit=paraInertiaUnit.DefValue;
  200.     first=true;
  201.     SetOutputMode(true);
  202. }
  203.  
  204.  
  205. unsigned long mi::calculate_length(byte type, word len)
  206. {
  207.     unsigned long length;
  208.     switch(type)
  209.     {
  210.     case 0:
  211.         length=len*pMasterInfo->SamplesPerTick;
  212.         break;
  213.     case 1:
  214.         length=(len*pMasterInfo->SamplesPerTick)/256;
  215.         break;
  216.     case 2:
  217.         length=len;
  218.         break;
  219.     case 3:
  220.         length=(len*pMasterInfo->SamplesPerSec)/1000;
  221.         break;
  222.     case 4:
  223.         length=len*pMasterInfo->SamplesPerSec;
  224.         break;
  225.     }
  226.     return length;
  227. }
  228.  
  229.  
  230. void mi::Tick()
  231. {
  232.  
  233.   int tmpMode;
  234.  
  235.   // inertia parameters
  236.  
  237.   if (gval.inertia != paraInertia.NoValue)
  238.   {
  239.     valInertia=gval.inertia;
  240.   }
  241.   if (gval.inertiaunit != paraInertiaUnit.NoValue)
  242.   {
  243.     valInertiaUnit=gval.inertiaunit;
  244.   }
  245.  
  246.   if (gval.mode != paraMode.NoValue)
  247.   {
  248.       tmpMode=gval.mode;
  249.   } else
  250.   {
  251.       tmpMode=valMode;
  252.   }
  253.  
  254.   // right fader parameters
  255.  
  256.   if (gval.rxfade != paraRXFade.NoValue)
  257.   {
  258.     r_counter=calculate_length(valInertiaUnit,valInertia);
  259.     valRFade=((float)gval.rxfade)/0xfe;
  260.     switch(tmpMode)
  261.     {
  262.     case 0: // separate
  263.         r_inertia=true;
  264.         r_amp_target=valRFade;
  265.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  266.         break;
  267.     case 1: // linked
  268.     case 4: // right master
  269.         r_inertia=true;
  270.         r_amp_target=valRFade;
  271.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  272.  
  273.         l_counter=r_counter;
  274.         l_amp_target=r_amp_target;
  275.         l_inertia=true;
  276.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  277.         break;
  278.     case 3: // left master
  279.         break;
  280.     case 2: // mirror
  281.         r_inertia=true;
  282.         r_amp_target=valRFade;
  283.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  284.  
  285.         l_counter=r_counter;
  286.         l_amp_target=(float)(1.0-r_amp_target);
  287.         l_inertia=true;
  288.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  289.         break;
  290.     }
  291.   }
  292.  
  293.   // left fader parameters
  294.  
  295.   if (gval.lxfade != paraLXFade.NoValue)
  296.   {
  297.     l_counter=calculate_length(valInertiaUnit,valInertia);
  298.     valLFade=((float)gval.lxfade)/0xfe;
  299.     switch(tmpMode)
  300.     {
  301.     case 0: // separate
  302.         l_inertia=true;
  303.         l_amp_target=valLFade;
  304.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  305.         break;
  306.     case 1: // linked
  307.     case 3: // left master
  308.         l_inertia=true;
  309.         l_amp_target=valLFade;
  310.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  311.  
  312.         r_counter=l_counter;
  313.         r_amp_target=l_amp_target;
  314.         r_inertia=true;
  315.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  316.         break;
  317.     case 4: // right master
  318.         break;
  319.     case 2: // mirror
  320.         l_inertia=true;
  321.         l_amp_target=valLFade;
  322.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  323.  
  324.         r_counter=l_counter;
  325.         r_amp_target=(float)(1.0-l_amp_target);
  326.         r_inertia=true;
  327.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  328.         break;
  329.     }
  330.   }
  331.  
  332.   // mode parameters
  333.  
  334.   if (gval.mode != paraMode.NoValue)
  335.   {
  336.     if(valMode!=gval.mode)
  337.     {
  338.         // set the beginning values for the mode to the defaults
  339.         switch(gval.mode)
  340.         {
  341.         case 0: // separate
  342.         case 1: // linked
  343.         case 2: // mirror
  344.             l_amp_target=valLFade;
  345.             r_amp_target=valRFade;
  346.             break;
  347.         case 3: // left master
  348.             l_amp_target=valLFade;
  349.             r_amp_target=valLFade;
  350.             break;
  351.         case 4: // right master
  352.             l_amp_target=valRFade;
  353.             r_amp_target=valRFade;
  354.             break;
  355.         }
  356.  
  357.         // make a fade to the new parameter.
  358.  
  359.         if(aval.maxdelay)
  360.         {
  361.             r_counter=l_counter=calculate_length(valInertiaUnit,valInertia);
  362.         } else
  363.         {
  364.             r_counter=l_counter=calculate_length(0,1)/2;
  365.         }
  366.  
  367.         r_inertia=true;
  368.         r_amp_inc=(r_amp_target-r_r_amp)/r_counter;
  369.         l_inertia=true;
  370.         l_amp_inc=(l_amp_target-l_r_amp)/l_counter;
  371.     }
  372.     valMode=gval.mode;
  373.   }
  374.  
  375.   // bypasses inertia on the first tick() to prevent the machine warmup effect
  376.   // sets inertia to 0 so that the amp values are effective immediatly
  377.   if(first)
  378.   {
  379.     r_inertia=true;
  380.     r_counter=0;
  381.     l_inertia=true;
  382.     l_counter=0;
  383.     first=false;
  384.   }
  385.  
  386.  
  387.  
  388. bool mi::MDKWorkStereo(float *psamples, int numsamples, int const mode)
  389. {
  390.     float l,r;
  391.     if ((mode==WM_WRITE)||(mode==WM_NOIO))
  392.     {
  393.         return false;
  394.     }
  395.  
  396.     if (mode == WM_READ)        // <thru>
  397.         return true;
  398.  
  399.     do 
  400.     {
  401.         if(l_inertia)
  402.         {
  403.             l_r_amp+=l_amp_inc;
  404.             if(!(l_counter--))
  405.             {
  406.                 l_inertia=false;
  407.                 l_r_amp=l_amp_target;
  408.             }
  409.             l_l_amp=(float)(1.0-l_r_amp);
  410.         }
  411.         if(r_inertia)
  412.         {
  413.             r_r_amp+=r_amp_inc;
  414.             if(!(r_counter--))
  415.             {
  416.                 r_inertia=false;
  417.                 r_r_amp=r_amp_target;
  418.             }
  419.             r_l_amp=(float)(1.0-r_r_amp);
  420.         }
  421.         l=psamples[0];
  422.         r=psamples[1];
  423.         psamples[0]=l_l_amp*l+r_l_amp*r;
  424.         psamples[1]=l_r_amp*l+r_r_amp*r;
  425.         psamples+=2;
  426.     } while(--numsamples);
  427.  
  428.     return true;
  429. }
  430.